﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="StudyDefinitionMapper.cs" company="ELEN 7045 GROUP II">>
//   Contributed by E.Vosloo
// </copyright>
// <summary>
//   A class used to Map studies.
//   This class was created to work around an issue in AutoMapper which is the tool of choice for mapping entities to dtos.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Presentation.Module.StudyDefinition.Services.Mappers
{
    #region

    using System;
    using System.Collections.ObjectModel;

    using Presentation.Module.StudyDefinition.Models;

    using Treatment = Domain.StudyDefinition.Entities.Treatment;

    #endregion

    /// <summary>
    /// A class used to Map studies. 
    /// This class was created to work around an issue in AutoMapper which is the tool of choice for mapping entities to dtos.
    /// </summary>
    internal class StudyDefinitionMapper
    {
        #region Methods

        /// <summary>
        /// Maps a study entity to a study model
        /// </summary>
        /// <param name="study">
        /// The study.
        /// </param>
        /// <returns>
        /// A study model
        /// </returns>
        internal static Study EntityToModel(Domain.StudyDefinition.Entities.Study study)
        {
            if (study == null)
            {
                throw new ArgumentNullException("study");
            }

            Study model = new Study();

            model.Id = study.Id;
            model.IsLocked = study.IsLocked;
            model.Archivable = study.Archivable;
            model.CompletionDate = study.CompletionDate;
            model.CreatedBy = study.CreatedBy;
            model.CreationDate = study.CreationDate;
            model.Description = study.Description;
            model.ModifiedBy = study.ModifiedBy;
            model.ModifiedDate = study.ModifiedDate;
            model.Reference = study.Reference;
            model.Title = study.Title;
            model.CustomerName = study.CustomerName;

            if (study.Treatments != null)
            {
                model.Treatments = new ObservableCollection<Models.Treatment>();
                foreach (var treatment in study.Treatments)
                {
                    model.Treatments.Add(EntityToModel(treatment));
                }
            }
            
            return model;
        }

        /// <summary>
        /// Maps ad subject group entity to subject group model.
        /// </summary>
        /// <param name="subjectGroup">
        /// The subject group.
        /// </param>
        /// <returns>
        /// A subject model
        /// </returns>
        internal static SubjectGroup EntityToModel(Domain.StudyDefinition.Entities.SubjectGroup subjectGroup)
        {
            if (subjectGroup == null)
            {
                throw new ArgumentNullException("subjectGroup");
            }

            SubjectGroup model =
            new SubjectGroup();

            model.Id = subjectGroup.Id;
            model.Name = subjectGroup.Name;
            
            if (subjectGroup.Subjects != null)
            {
                model.Subjects = new ObservableCollection<Subject>();

                foreach (var subject in subjectGroup.Subjects)
                {
                    model.Subjects.Add(
                        new Subject
                            {
                                Id = subject.Id, 
                                IsPrimary = subject.IsPrimary, 
                                SpecialIdentification = subject.SpecialIdentification
                            });
                }
            }

            return model;
        }

        /// <summary>
        /// Maps a treatment entity to treatment model.
        /// </summary>
        /// <param name="treatment">
        /// The treatment.
        /// </param>
        /// <returns>
        /// A treatment model
        /// </returns>
        internal static Models.Treatment EntityToModel(Treatment treatment)
        {
            if (treatment == null)
            {
                throw new ArgumentNullException("treatment");
            }

            Models.Treatment model = new Models.Treatment();
            model.Description = treatment.Description;
            model.Id = treatment.Id;
            model.Name = treatment.Name;


            if (treatment.SubjectGroups != null)
            {
                model.SubjectGroups = new ObservableCollection<SubjectGroup>();

                foreach (var subjectGroup in treatment.SubjectGroups)
                {
                    model.SubjectGroups.Add(EntityToModel(subjectGroup));
                }
            }

            if (treatment.PlannedTasks != null)
            {
                model.PlannedTasks = new ObservableCollection<PlannedTask>();

                foreach (var plannedTask in treatment.PlannedTasks)
                {
                    var modelplannedTask = new PlannedTask();

                    modelplannedTask.Id = plannedTask.Id;
                    modelplannedTask.Name = plannedTask.Name;
                    modelplannedTask.Description = plannedTask.Description;
                    modelplannedTask.RequiresAssistant = plannedTask.RequiresAssistant;
                    modelplannedTask.RoundId = plannedTask.RoundNumber;
                    
                    modelplannedTask.IsRoundTroubleshooter = plannedTask.IsRoundTroubleshooter;
                    modelplannedTask.ProtocolTime = plannedTask.SuggestedPlan.ProtocolTime;
                    modelplannedTask.IsKeyStoneTask = plannedTask.SuggestedPlan.IsKeyStoneTask;
                    modelplannedTask.SetupDuration = plannedTask.SuggestedPlan.SetupDuration;

                    model.PlannedTasks.Add(modelplannedTask);
                }
            }

            return model;
        }

        /// <summary>
        /// Maps a study model to a study entity
        /// </summary>
        /// <param name="study">
        /// The study.
        /// </param>
        /// <returns>
        /// A study entity
        /// </returns>
        internal static Domain.StudyDefinition.Entities.Study ModelToEntity(Study study)
        {
            if (study == null)
            {
                throw new ArgumentNullException("study");
            }

            Domain.StudyDefinition.Entities.Study entity = new Domain.StudyDefinition.Entities.Study();

            entity.Id = study.Id;
            entity.Description = study.Description;
            entity.Reference = study.Reference;
            entity.Title = study.Title;
            entity.CustomerName = study.CustomerName;

            if (study.Treatments != null)
            {
                entity.Treatments = new Collection<Treatment>();

                foreach (var treatment in study.Treatments)
                {
                    entity.Treatments.Add(ModelToEntity(treatment));
                }
            }


            return entity;
        }

        /// <summary>
        /// Maps ad subject group model to subject group entity.
        /// </summary>
        /// <param name="subjectGroup">
        /// The subject group.
        /// </param>
        /// <returns>
        /// A subject entity
        /// </returns>
        internal static Domain.StudyDefinition.Entities.SubjectGroup ModelToEntity(SubjectGroup subjectGroup)
        {
            if (subjectGroup == null)
            {
                throw new ArgumentNullException("subjectGroup");
            }

            Domain.StudyDefinition.Entities.SubjectGroup entity =
                new Domain.StudyDefinition.Entities.SubjectGroup();

            entity.Id = subjectGroup.Id;
            entity.Name = subjectGroup.Name;
            
            if (subjectGroup.Subjects != null)
            {
                entity.Subjects = new Collection<Domain.StudyDefinition.Entities.Subject>();

                foreach (var subject in subjectGroup.Subjects)
                {
                    entity.Subjects.Add(
                        new Domain.StudyDefinition.Entities.Subject
                            {
                                IsPrimary = subject.IsPrimary, 
                                SpecialIdentification = subject.SpecialIdentification
                            });
                }
            }

            return entity;
        }

        /// <summary>
        /// Maps a treatment model to a treatment entity.
        /// </summary>
        /// <param name="treatment">
        /// The treatment.
        /// </param>
        /// <returns>
        /// A treatment entity
        /// </returns>
        internal static Treatment ModelToEntity(Models.Treatment treatment)
        {
            if (treatment == null)
            {
                throw new ArgumentNullException("treatment");
            }


            Treatment entity = new Treatment();
            entity.Description = treatment.Description;
            entity.Id = treatment.Id;
            entity.Name = treatment.Name;

            if (treatment.SubjectGroups != null)
            {
                entity.SubjectGroups = new Collection<Domain.StudyDefinition.Entities.SubjectGroup>();

                foreach (var subjectGroup in treatment.SubjectGroups)
                {
                    entity.SubjectGroups.Add(ModelToEntity(subjectGroup));
                }
            }

            if (treatment.PlannedTasks != null)
            {
                entity.PlannedTasks = new Collection<Domain.StudyDefinition.Entities.PlannedTask>();

                foreach (var plannedTask in treatment.PlannedTasks)
                {
                    var entplannedTask = new Domain.StudyDefinition.Entities.PlannedTask();
                    
                    entplannedTask.Description = plannedTask.Description;
                    entplannedTask.Id = plannedTask.Id;
                    entplannedTask.SuggestedPlan.IsKeyStoneTask = plannedTask.IsKeyStoneTask;
                    entplannedTask.IsRoundTroubleshooter = plannedTask.IsRoundTroubleshooter;
                    entplannedTask.Name = plannedTask.Name;
                    entplannedTask.SuggestedPlan.ProtocolTime = plannedTask.ProtocolTime;
                    entplannedTask.RequiresAssistant = plannedTask.RequiresAssistant;
                    entplannedTask.RoundNumber = plannedTask.RoundId;
                    entplannedTask.SuggestedPlan.SetupDuration = plannedTask.SetupDuration;
                    
                    entity.PlannedTasks.Add(entplannedTask);
                }
            }

            return entity;
        }

        #endregion
    }
}
